package com.example.demoeventspring.configuration;

import com.example.demoeventspring.executor.VisiableThreadPoolTaskExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步监听配置
 */
@Slf4j
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
    /**
     * 获取异步线程池执行对象
     *
     * @return
     */
    @Override
    @Bean("AsyncTaskExecutor")
    public Executor getAsyncExecutor() {
        //使用Spring内置线程池任务对象 每次提交线程的时候都会将当前线程池的运行状况打印出来
        ThreadPoolTaskExecutor taskExecutor = new VisiableThreadPoolTaskExecutor();
        //设置线程池参数
        taskExecutor.setCorePoolSize(5);
        //连接池中保留的最大连接数。
        taskExecutor.setMaxPoolSize(100);
        //queueCapacity 线程池所使用的缓冲队列
        taskExecutor.setQueueCapacity(9999);
        //配置线程池中的线程的名称前缀
        taskExecutor.setThreadNamePrefix("Spring AsyncTaskExecutor Thread-");
        //设置线程空闲后的存活时间，单位秒。可以在运行时修改。若未设置，则默认为 60 。
        taskExecutor.setKeepAliveSeconds(300);
        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
        // ThreadPoolExecutor#DiscardPolicy：这个策略将会直接丢弃任务
        // ThreadPoolExecutor#CallerRunsPolicy：不在新线程中执行任务，而是有调用者所在的线程来执行策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("error,method={},throwable={}", method, throwable);
        };
    }
}
